/*
 * SubServer.java
 *
 * Created on August 11, 2006, 12:36 AM
 *
 */
package org.letva.copie.subserver;

import java.io.*;
import java.net.*;
import java.util.*;
import org.letva.copie.subserver.listeners.*;
import org.letva.copie.subserver.gui.*;
import org.letva.copie.common.message.SubServerInfo;
import org.letva.copie.subserver.threads.*;

/**
 *
 * @author Vuk Nikolic
 */
public class SubServer {

	/** Creates a new instance of SubServer */
	public SubServer(SubServerWindow frame, int mp, int sp, int cp, String fileName) {
		myWindow = frame;
		createProtocol();
		try {
			mainServerPort = mp;
			subServerPort = sp;
			clientPort = cp;
			createLog(fileName);
			writeLog("Log started.");
		} catch (IOException e) {
			myWindow.setDialogException("Local Error.", "Cannot make the log file.");
		}

		startMainServerListener();
	}

	public void createLog(String fileName) throws IOException {
		logFile = new File(fileName);
		log = new PrintWriter(new FileWriter(logFile));
	}

	public void connectToMainServer(String host, int port) throws SocketException,
			SocketTimeoutException, UnknownHostException, IOException {
		// da uspostavi vezu sa main serverom i
		// da napravi novu nit koja ce mu periodicno slati poruke.

		// ako vec postoji aktivan main server nemoj ga praviti
		if (activeMainServerThreads == 0) {
			serverSocket = new Socket(host, port);
			serverSocket.setSoTimeout(timeout);
			mainServerThread = new MainServerThread(serverSocket, this);
			mainServerThread.start();
			incActiveMainServerThreads();
			writeLog("MainServerThread started.");
		}

	}

	public void startMainServerListener() {
		mainServerListener = new MainServerListener(this);
		mainServerListener.start();
		writeLog("MainServerListener started.");
	}

	public void startSubServerListener() {
		subServerListener = new SubServerListener(this);
		subServerListener.start();
		writeLog("SubServerListener started.");
	}

	public void stopSubServerListener() {
		if (subServerListener != null) {
			subServerListener.stopSubServerListener();
		}
	}

	public void startClientListener() {
		clientListener = new ClientListener(this);
		clientListener.start();
		writeLog("ClientListener started.");
	}

	public void stopClientListener() {
		if (clientListener != null) {
			clientListener.stopClientListener();
		}
	}

	public void start() {
		subServerListener.start();
		clientListener.start();
		System.out.println("SubServer: start: napravili smo startovali threadove");
	}

	public void stop() {
		if (subServerListener != null) {
			subServerListener.stopSubServerListener();
		}
	}

	private void createProtocol() {
		if (myProtocol == null) {
			myProtocol = new SubServerProtocol(this);
		}
	}

	public static SubServerProtocol getProtocol() {
		return myProtocol;
	}

	public synchronized LinkedList getSubServerThreads() {
		return subServerThreads;
	}

	public synchronized LinkedList getActiveSubServers() {
		return activeSubServers;
	}

	public synchronized void setActiveSubServers(LinkedList ll) {
		activeSubServers = ll;
	}

	public synchronized HashMap getConnectedSubServers() {
		return connectedSubServers;
	}

	public synchronized void addConnectedSubServer(SubServerInfo ssi) {
		connectedSubServers.put(ssi.getUrl(), ssi);
	}

	public synchronized void removeConnectedSubServer(SubServerInfo ssi) {
		connectedSubServers.remove(ssi.getUrl());
	}

	public synchronized void removeConnectedSubServer(String url) {
		connectedSubServers.remove(url);
	}

	public int getNextSubServerId() {
		return totalSubServerId++;
	}

	public int getMainServerOnDemandPort() {
		return mainServerOnDemandPort;
	}

	public int getMainServerPort() {
		return mainServerPort;
	}

	// port na koji se kace ovi ostali.
	public int getSubServerPort() {
		return subServerPort;
	}

	public void setSubServerPort(int p) {
		subServerPort = p;
	}

	public int getClientPort() {
		return clientPort;
	}

	public void setClientPort(int p) {
		clientPort = p;
	}

	public synchronized void incActiveClientThreads() {
		activeClientThreads++;
		myWindow.setConnctedClientsLabel(activeClientThreads + "");
	}

	public synchronized void decActiveClientThreads() {
		activeClientThreads--;
		myWindow.setConnctedClientsLabel(activeClientThreads + "");
	}

	public synchronized void incActiveSubServerThreads() {
		activeSubServerThreads++;
	}

	public synchronized void decActiveSubServerThreads() {
		activeSubServerThreads--;
	}

	public synchronized void incActiveMainServerThreads() {
		activeMainServerThreads++;
	}

	public synchronized void decActiveMainServerThreads() {
		activeMainServerThreads--;
	}

	public int getTimeout() {
		return timeout;
	}

	public SubServerWindow getMyWindow() {
		return myWindow;
	}

	public synchronized void incNetworkOperations() {
		networkOperations++;
	}

	public synchronized void decNetworkOperations() {
		networkOperations--;
	}

	public int getNetworkOperations() {
		return networkOperations;
	}

	public synchronized void writeLog(String s) {
		try {
			log = new PrintWriter(new FileWriter(logFile, true));
			log.println("[" + new Date() + "] " + s);
			log.close();
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	// svi povezani podeserveri na ovaj podserver
	private HashMap connectedSubServers = new HashMap();
	// svi aktivni podserveri, to dobijam od mainServera
	private LinkedList activeSubServers = new LinkedList();
	// protokol po kome radi
	private static SubServerProtocol myProtocol = null;
	// nit koja osluskije da li neki client zeli da se nakaci
	private ClientListener clientListener = null;
	// nit koja osluskuje da li neki subserver zeli da se nakaci
	private SubServerListener subServerListener = null;
	private MainServerListener mainServerListener = null;
	// nit koja salje podatke MainServeru
	private MainServerThread mainServerThread = null;
	private PrintWriter log = null;
	// putanja do log fajla
	private String logFileName = "log.txt";
	// sam log file
	private File logFile = null;
	private int activeMainServerThreads = 0;
	private int activeSubServerThreads = 0;
	private int activeClientThreads = 0;
	private int clientPort = 7770;
	private int subServerPort = 7771;
	private int mainServerPort = 7772;
	private int mainServerOnDemandPort = 7773;
	// za komunikaciju sa glavnim serverom
	private Socket serverSocket = null;
	// za identifikaciju subservera
	private static int totalSubServerId = 0;
	// lista svih threadova koji rade sa podserverima
	private LinkedList subServerThreads = null;
	private int timeout = 10000;
	private SubServerWindow myWindow = null;
	private int networkOperations = 0;
}
